



class axi_driver extends uvm_driver #(axi_seq_item);

 
  virtual axi_if vif;
  `uvm_component_utils(axi_driver)
    
  
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new

  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
     if(!uvm_config_db#(virtual axi_if)::get(this, "", "vif", vif))
       `uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
  endfunction: build_phase

   
  virtual task run_phase(uvm_phase phase);
    forever begin
      seq_item_port.get_next_item(req);
      drive();
      seq_item_port.item_done();
    end
  endtask : run_phase
  
  
  
  virtual task drive();
             
    @(posedge vif.aclk_i);
    @(posedge vif.aclk_i);
      
    wait(vif.areset_n_i == 1);
        
    if(req.write_start_i) begin
          
      vif.write_start_i     <= req.write_start_i;
      vif.write_length_i    <= req.write_length_i;
      vif.write_burst_i     <= req.write_burst_i;
      vif.write_size_i      <= req.write_size_i;  
      vif.write_lock_i      <= req.write_lock_i; 
      vif.write_awid_i      <= req.write_awid_i;
      vif.write_wid_i       <= req.write_wid_i;
      vif.write_addr_i      <= req.write_addr_i;
      vif.write_datav_i     <= req.write_datav_i; 
      vif.write_data_i      <= req.write_data_i;
      vif.write_strb_i      <= req.write_strb_i;        
    
      if(req.write_length_i == 4'b0000)
        begin
          wait(vif.write_ack_o);
          @(posedge vif.aclk_i);
          req.write_start_i      = 0;
          vif.write_start_i     <= req.write_start_i;
        end
          
      else if(req.write_length_i != 4'b0000)
        begin
          wait(vif.write_ack_o && vif.write_data_req_o)        
          vif.write_data_i       <= req.write_data_i;
          @(posedge vif.aclk_i);
          
          req.write_start_i       = 0;
          vif.write_start_i      <= req.write_start_i;
          vif.write_data_i       <= req.write_data_i;
  
          for(int i =1;i<req.write_length_i ;i++) begin        
        	@(posedge vif.aclk_i);
        	wait(vif.write_data_req_o);  
        	req.write_datav_i        = 1;
            vif.write_data_i       <= req.write_data_i;
        	vif.write_datav_i       <= req.write_datav_i;
                     end
        end
            
      req.write_data_req_o =  vif.write_data_req_o;
      req.write_done_o     =  vif.write_done_o;
      req.write_err_o      =  vif.write_err_o;
      req.write_bid_o      =  vif.write_bid_o;
      req.write_bvalid_o   =  vif.write_bvalid_o;    
      req.write_bresp_o    =  vif.write_bresp_o;  
        
      wait(vif.write_done_o);
      @(posedge vif.aclk_i);
      req.write_datav_i       = 0;
      vif.write_datav_i      <= req.write_datav_i;
    end
  
    @(posedge vif.aclk_i);
    
      
    if(req.read_start_i) begin
       
      vif.read_start_i    <= req.read_start_i;
      vif.read_arid_i     <= req.read_arid_i;
      vif.read_addr_i     <= req.read_addr_i;
      vif.read_length_i   <= req.read_length_i;
      vif.read_size_i     <= req.read_size_i;  
      vif.read_burst_i    <= req.read_burst_i; 
      vif.read_lock_i     <= req.read_lock_i;
      vif.read_af_i       <= req.read_af_i;
     
   
      wait(vif.read_ack_o);
      @(posedge vif.aclk_i);
      
      req.read_start_i      = 0; 
      vif.read_start_i     =  req.read_start_i;
      req.read_ack_o    =  vif.read_ack_o;
      
            
      wait(vif.read_datav_o);
      
      req.read_data_o   =  vif.read_data_o;
      req.read_datav_o  =  vif.read_datav_o;
      req.read_err_o    =  vif.read_err_o;
      req.read_done_o   =  vif.read_done_o;
    end  
     
  endtask : drive
endclass : axi_driver